/**  
  -- The Performance Driven Lime Project -- 

  A self adaptive tuple space for mobile agents and hosts by dynamic
  adapting tuple's replication policy.
  
  Copyright (C) 2008
  Xing Jiankuan, Pan Wenhui
  SAGroup of Tsinghua University

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received this copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 
 */
package sagroup.dracots;

import java.util.Hashtable;

import sagroup.dracots.TupleType;
import lime2.TupleID;
/**
 * @author Xing Jiankuan
 *
 */
public class VersionManager {

   	private Hashtable<TupleID, VersionRecord> records;
	private CostManager costQueue;

	/**
	 * 
	 */
	public VersionManager(CostManager costQueue) {
		records = new Hashtable<TupleID, VersionRecord>();
		this.costQueue = costQueue;
	}

	/**
	 * Invoked when tuple whose master is remote is read.
	 * Maintain the tuple version info and to adjust relevant update count records.
	 * @param tupleId
	 * @param type
	 * @param version
	 * @param period
	 * @author Xing Jiankuan
	 */
	public synchronized void updateVersionRecord(TupleID tupleId,
			TupleType type, long version, Period period) {

		if(period == null) 
			return;
		if (!records.containsKey(tupleId)) {
			records.put(tupleId, new VersionRecord(tupleId, type, version,
					period));
			costQueue.addTupleType(type,period);
		} else {
			VersionRecord record = records.get(tupleId);

			long oldVersion = record.getVersion();
			Period oldPeriod = record.getPeriod();
//			costQueue.updateSOWriteCount(tupleId, type, oldVersion, oldPeriod,
//					version, period);

			record.update(version, period);
		}
	}

    /**
     * For test only.
     * @return
     * @author Xing Jiankuan
     */
	public synchronized Hashtable<TupleID, VersionRecord> getVersionRecords() {
		
		return records;
	}
    /**
     * Invoked when local replica is updated.
     * Avoiding recalculate of write count for a certain type.
     * @param tupleId
     * @param type
     * @param version
     * @param period
     * @author Xing Jiankuan
     */

	public synchronized void updateVersionWithReplica(TupleID tupleId,
			TupleType type, long version, Period period) {
		if (!records.containsKey(tupleId)) {
			records.put(tupleId, new VersionRecord(tupleId, type, version,
					period));
		} else {
			VersionRecord record = records.get(tupleId);
			record.update(version, period);
		}
	}

}

class VersionRecord {
	private TupleID tupleId; 
	private long version;
	private Period period;
	private TupleType type;

	public VersionRecord(TupleID tupleId, TupleType type, long version,
			Period period) {
		this.tupleId = tupleId;
		this.version = version;
		this.period = period;
		this.type = type;
	}

	public Period getPeriod() {
		return period;
	}

	public long getVersion() {
		return version;
	}

	public void update(long version, Period period) {
		this.period = period;
		this.version = version;
	}

}